<template>
  <div class="demand-page-box">
    <div class="page-container">
      <el-row>
        <el-col :span="6">
          <div class="menu-tree-box">
            <!-- 菜单名称的关键词筛选 -->
            <el-input size="mini" placeholder="请输入菜单名称筛选" v-model="menuFilterText"></el-input>
            <!-- 树形结构 -->
            <!-- :render-content="renderContent" -->
            <el-tree :data="menuTreeData" :props="treeProps" node-key="id" :filter-node-method="filterNode" ref="menuTree" highlight-current draggable :allow-drop="allowDrop" @node-click="handleNodeClick" @node-drag-end="handleDragNode" :allow-drag="nodeCanDrag" default-expand-all></el-tree>
          </div>
        </el-col>
        <el-col :span="18">
          <template v-if="clickNode == 'menu'">
            <!-- 检索条件 -->
            <div class="form-parent-newbox1">
              <div class="form-title-area">
                <h4>菜单信息</h4>
              </div>
              <el-descriptions>
                <el-descriptions-item label="菜单编码">{{
                  menuInfo.code
                }}</el-descriptions-item>
                <el-descriptions-item label="菜单名称">{{
                  menuInfo.title
                }}</el-descriptions-item>
              </el-descriptions>
            </div>
            <!-- 表格 -->
            <el-row>
              <!-- 所有角色列表 -->
              <el-col :span="11">
                <div class="table-buttons-box">
                  <h4 style="padding: 0 0 10px 10px">所有角色</h4>
                </div>
                <el-table ref="allRolesTable" :data="allRolesList" tooltip-effect="dark" style="width: 100%" height="80vh" border :header-cell-style="{
                    background: '#FAFAFA',
                    color: '#262626',
                    textAlign: 'center',
                  }" highlight-current-row @selection-change="handleSelectionChange1">
                  <el-table-column align="center" width="80" label="序号" type="index" :index="indexMethod"></el-table-column>
                  <el-table-column type="selection" width="55"> </el-table-column>
                  <el-table-column sortable align="center" prop="name" label="角色名称" min-width="120"></el-table-column>
                </el-table>
              </el-col>
              <!-- 中间两个图标，移除/添加 -->
              <el-col :span="2">
                <div class="icon-box">
                  <i class="el-icon-d-arrow-right" @click="handleAddRole"></i>
                </div>
                <div class="icon-box">
                  <i class="el-icon-d-arrow-left" @click="handleRemoveRole"></i>
                </div>
              </el-col>
              <!-- 该菜单已经授权的角色 -->
              <el-col :span="11">
                <div class="table-buttons-box">
                  <h4 style="padding: 0 0 10px 10px">已授权角色</h4>
                </div>
                <el-table ref="authorizedRolesTable" :data="authorizedRoles" tooltip-effect="dark" style="width: 100%" height="80vh" border :header-cell-style="{
                    background: '#FAFAFA',
                    color: '#262626',
                    textAlign: 'center',
                  }" highlight-current-row @selection-change="handleSelectionChange2">
                  <el-table-column align="center" width="80" label="序号" type="index" :index="indexMethod"></el-table-column>
                  <el-table-column type="selection" width="55"> </el-table-column>
                  <el-table-column sortable align="center" prop="roleName" label="角色名称" min-width="120"></el-table-column>
                </el-table>
              </el-col>
            </el-row>
          </template>
          <template v-else>
            <div class="table-buttons-box">
              <h4 style="padding: 0 0 10px 10px">菜单列表</h4>
              <el-button v-if="!!currGroupId" type="primary" size="mini" @click="handleAddMenu">添加</el-button>
            </div>
            <el-table ref="tb" :data="sonMenus" tooltip-effect="dark" style="width: 100%" :height="tableHeight" border :header-cell-style="{
                background: '#FAFAFA',
                color: '#262626',
                textAlign: 'center',
              }" highlight-current-row>
              <el-table-column align="center" width="80" label="序号" type="index" :index="indexMethod"></el-table-column>
              <el-table-column sortable align="center" prop="title" label="菜单名称" min-width="120"></el-table-column>
              <el-table-column sortable align="center" prop="code" label="菜单编码" min-width="120"></el-table-column>
              <el-table-column sortable align="center" label="菜单类型" min-width="120">
                <template slot-scope="scope">
                  <span>{{scope.row.type == "group" ? "菜单分组" : scope.row.type == "menu" ? "菜单" : ""}}</span>
                </template>
              </el-table-column>
              <el-table-column sortable align="center" prop="path" label="菜单路径" min-width="120"></el-table-column>
              <el-table-column sortable align="left" prop="remark" label="备注" min-width="120" show-overflow-tooltip></el-table-column>
              <el-table-column align="center" fixed="right" label="操作" width="100">
                <template slot-scope="scope">
                  <el-button type="text" size="mini" @click="handleUpdateMenu(scope.row)">编辑</el-button>
                  <el-button type="text" size="mini" @click="handleDeleteMenu(scope.row)">删除</el-button>
                </template>
              </el-table-column>
            </el-table>
          </template>
        </el-col>
      </el-row>
    </div>
    <!-- 添加或编辑菜单   -->
    <el-dialog :title="showAddMenuTKTitle" width="80%" :append-to-body="true" :visible.sync="showAddMenuTK" :close-on-click-modal="false" :close-on-press-escape="false">
      <el-form label-width="100px" label-position="left" :model="createMenuInfo" :rules="rules" ref="createMenuInfo">
        <el-form-item label="菜单名称" prop="menuName">
          <el-input type="text" v-model="createMenuInfo.menuName" placeholder="请输入"></el-input>
        </el-form-item>
        <el-form-item label="菜单编码" prop="menuCode">
          <el-input type="text" v-model="createMenuInfo.menuCode" placeholder="请输入"></el-input>
        </el-form-item>
        <el-form-item label="菜单类型" prop="menuType">
          <el-select filterable clearable placeholder="请选择" v-model="createMenuInfo.menuType">
            <el-option v-for="item in menuTypeList" :key="item.code" :label="item.name" :value="item.code"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="菜单路径">
          <el-input type="text" v-model="createMenuInfo.menuPath" placeholder="请输入"></el-input>
        </el-form-item>
        <el-form-item label="备注">
          <el-input type="textarea" :rows="3" v-model="createMenuInfo.remark" placeholder="请输入"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button size="mini" icon="el-icon-close" @click="showAddMenuTK = false">取消</el-button>
        <el-button size="mini" icon="el-icon-check" type="primary" @click="handleSaveMenu">保存</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<script>
let me;
import Pagination from "@/components/common/pagination";
import publicFunc from "@/resources/js/publicFunc";
import { roleList, allRoleList } from "@/api/permissionManage/role.api";
import {
  menuTreeList,
  addMenu,
  updateMenu,
  deleteMenu,
  menuRoleList,
  setMenuRole,
  removeMenuRole,
} from "@/api/permissionManage/menu.api";
export default {
  data() {
    return {
      // 左半边菜单 树形图
      menuFilterText: "", // 输入的过滤关键字
      allMenus: [],// 接口返回的全部菜单
      menuTreeData: [],// 接口返回的全部菜单 转成树形结构
      treeProps: {
        label: "title",
      },
      clickNode: "", // 点的是菜单分组还是菜单
      currGroupId: "", // 当前的分组id
      publicFunc: publicFunc,
      menuInfo: {
        code: "",
        title: "",
      },
      allRolesList: [],
      selectRoles: [],
      authorizedRoles: [],
      selectAuthorizedRoles: [],
      //   菜单分组下的菜单列表
      sonMenus: [],
      // 添加新菜单
      showAddMenuTK: false,
      showAddMenuTKTitle: "",
      menuTypeList: [
        { code: "group", name: "菜单分组" },
        { code: "menu", name: "菜单" },
      ], // 菜单类型
      createMenuInfo: {
        id: "",
        menuName: "",
        menuCode: "",
        menuType: "",
        menuPath: "",
        remark: "",
      },
      rules: {
        menuName: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
        menuCode: [{ required: true, message: "请输入菜单编码", trigger: "blur" }],
        menuType: [{ required: true, message: "请选择菜单类型", trigger: "change" }],
      },
    };
  },
  watch: {
    // 组织的关键字变化时
    menuFilterText(val) {
      this.$refs.menuTree.filter(val);
    },
  },
  components: {
    Pagination,
  },
  computed: {
    tableHeight() {
      let formDom = document.querySelector(".form-parent-newbox1");
      let formHeight = formDom ? formDom.offsetHeight : 0;
      return window.innerHeight - formHeight - 48 - 20 + "px";
    },
  },
  mounted() {
    me = this;
    me.queryMenuTree();
    me.queryRoleList();
  },
  beforeDestroy() {
    window.onresize = function () { };
  },
  methods: {
    // 所有角色的表 勾选之后 可以添加授权
    handleSelectionChange1(e) {
      me.selectRoles = e;
    },
    // 已授权角色 勾选之后 可以移除角色
    handleSelectionChange2(e) {
      me.selectAuthorizedRoles = e;
    },
    // 当前勾选的角色，拼接上之前已经勾选的角色，roleCode做过去重之后
    handleAddRole() {
      if (me.selectRoles.length == 0) {
        publicFunc.showModalTips(me, "请选择要授权的角色");
        return;
      }
      // 哪些角色已经有过权限了
      let authorizedRoleCodes = me.authorizedRoles.map((item) => {
        return item.roleCode;
      })
      // 要追加哪些角色的权限
      let selectRoleCodes = me.selectRoles.map((item) => {
        return item.code;
      })
      let allRoleCodes = authorizedRoleCodes.concat(selectRoleCodes)
      // 封装参数，去调用授权接口
      let menuCodes = [me.menuInfo.code];
      // 找到当前菜单的父级菜单
      let parentMenu = me.allMenus.filter(item => {
        return item.id == me.menuInfo.pid
      })
      if (parentMenu.length > 0) {
        menuCodes.push(parentMenu[0].code);
      }
      let param = {
        menuCodes: menuCodes,
        roleCodes: Array.from(new Set(allRoleCodes)),
      };
      me.handleSetMenuRole(setMenuRole(param));
    },
    // 勾选了哪些角色 全部移除该菜单的权限
    handleRemoveRole() {
      if (me.selectAuthorizedRoles.length == 0) {
        publicFunc.showModalTips(me, "请选择要移除权限的角色");
        return;
      }
      let param = {
        menuCode: me.menuInfo.code,
        removeRoleList: me.selectAuthorizedRoles.map((item) => {
          return item.roleCode;
        }),
      };
      me.handleSetMenuRole(removeMenuRole(param));
    },
    // 添加或移除角色  公共的方法
    handleSetMenuRole(pro) {
      let rLoading = me.openLoading();
      pro.then((res) => {
        rLoading.close();
        if (res.code == "200") {
          me.$message.success("操作成功");
          me.queryAuthorizedRoles();
          me.$nextTick(() => {
            me.$refs.allRolesTable.clearSelection();
          });
        } else {
          me.$message.error(res.msg || "操作失败，请稍后再试~");
        }
      })
        .catch((err) => {
          rLoading.close();
          me.$message.error(err.statusText || "对不起，系统繁忙，请稍后再试~");
        });
    },
    /**
     * 添加一个菜单
     */
    handleAddMenu() {
      me.createMenuInfo.id = "";
      me.createMenuInfo.menuName = "";
      me.createMenuInfo.menuCode = "";
      me.createMenuInfo.menuType = "";
      me.createMenuInfo.menuPath = "";
      me.createMenuInfo.remark = "";
      me.showAddMenuTKTitle = "添加菜单";
      me.showAddMenuTK = true;
      me.$nextTick(() => {
        me.$refs.createMenuInfo.clearValidate();
      })
    },
    /**
     * 修改一个菜单
     */
    handleUpdateMenu(row) {
      me.createMenuInfo.id = row.id;
      me.createMenuInfo.menuName = row.title;
      me.createMenuInfo.menuCode = row.code;
      me.createMenuInfo.menuType = row.type;
      me.createMenuInfo.menuPath = row.path;
      me.createMenuInfo.remark = row.remark;
      me.showAddMenuTKTitle = "编辑菜单";
      me.showAddMenuTK = true;
      me.$nextTick(() => {
        me.$refs.createMenuInfo.clearValidate();
      })
    },
    /**
     * 新增或编辑一个菜单 
     */
    handleSaveMenu() {
      let errorTip = !me.createMenuInfo.menuName
        ? "请输入菜单名称"
        : !me.createMenuInfo.menuCode
          ? "请输入菜单编码"
          : !me.createMenuInfo.menuType
            ? "请选择菜单类型"
            : me.createMenuInfo.menuType == "menu" && !me.createMenuInfo.menuPath
              ? "请输入菜单路径"
              : "";
      if (!!errorTip) {
        me.$message.error(errorTip);
        return;
      }
      let param = {
        id: me.createMenuInfo.id || null,
        pid: me.currGroupId == "root" ? 0 : me.currGroupId,
        code: me.createMenuInfo.menuCode,
        title: me.createMenuInfo.menuName,
        menuType: me.createMenuInfo.menuType,
        path: me.createMenuInfo.menuPath,
        remark: me.createMenuInfo.remark,
      };
      let rLoading = me.openLoading();
      let pro = me.createMenuInfo.id ? updateMenu(param) : addMenu(param);
      pro
        .then((res) => {
          rLoading.close();
          if (res.code == "200") {
            me.$message.success("操作成功");
            me.queryMenuTree();
            me.showAddMenuTK = false;
            me.queryChildrenList();
          } else {
            me.$message.error(res.msg || "操作失败，请稍后再试~");
          }
        })
        .catch((err) => {
          rLoading.close();
          me.$message.error(err.statusText || "对不起，系统繁忙，请稍后再试~");
        });
    },
    /**
     * 删除一个菜单
     */
    handleDeleteMenu(item) {
      me.$alert(`您确认删除${item.title}吗？`, "温馨提示", {
        confirmButtonText: "确认",
        callback: (action) => {
          if (action == "confirm") {
            let rLoading = me.openLoading();
            deleteMenu({
              id: item.id,
            })
              .then((res) => {
                rLoading.close();
                if (res.code == "200") {
                  me.$message.success("已删除~");
                  me.queryMenuTree();
                  me.queryChildrenList();
                } else {
                  me.$message.error(res.msg || "删除失败，请稍后再试~");
                }
              })
              .catch((err) => {
                rLoading.close();
                me.$message.error(err.statusText || "对不起，系统繁忙，请稍后再试~");
              });
          }
        },
      });
    },
    // 根据id查询子节点
    queryChildrenList() {
      menuTreeList({
        pid: me.currGroupId,
      })
        .then((res) => {
          if (res.code == "200") {
            me.sonMenus = res.data;
          } else {
          }
        })
        .catch((err) => { });
    },
    // 查询角色列表
    queryRoleList() {
      allRoleList({})
        .then((res) => {
          if (res.code == "200") {
            me.allRolesList = res.data;
          } else {
            me.allRolesList = [];
          }
        })
        .catch((err) => {
          me.allRolesList = [];
        });
    },
    // 查询菜单树
    queryMenuTree() {
      var rLoading = me.openLoading();
      menuTreeList({})
        .then((res) => {
          rLoading.close();
          if (res.code == "200") {
            me.allMenus = res.data;
            me.menuTreeData = [
              {
                id: "root",
                title: "防疫管理后台",
                code: "fangyiManageRootNode",
                path: "",
                remark: "",
                children: convertToTree(res.data),
              },
            ];
          } else {
            me.$message.error(res.msg || "菜单查询失败，请稍后再试~");
          }
        })
        .catch((err) => {
          rLoading.close();
          me.$message.error(err.statusText || "对不起，系统繁忙，请稍后再试~");
        });
      // 扁平化数据转为树型结构数据
      function convertToTree(list) {
        var map = {};
        for (var item of list) {
          map[item.id] = item;
        }
        var root = {};
        for (var item of list) {
          var p = map[item.pid] || root;
          p.children = p.children || [];
          p.children.push(item);
        }
        return root.children;
      }
    },
    // 根据关键字过滤树形结构的数据
    filterNode(value, data) {
      if (!value) return true;
      return data.title.indexOf(value) !== -1;
    },
    // 选中一个部门，查询右侧表格数据
    handleNodeClick(e) {
      if (e.type == "menu") {
        // 如果是菜单，右侧展示的是该菜单的详情
        me.clickNode = "menu";
        me.menuInfo = e;
        me.queryAuthorizedRoles();
        me.$nextTick(() => {
          me.$refs.allRolesTable.clearSelection();
        });
      } else {
        // 否则是菜单分组，右侧展示的是该分组里的所有菜单
        me.clickNode = "menuGroup";
        me.currGroupId = e.id;
        me.sonMenus = e.children;
      }
    },
    // 查询当前菜单授权给哪些角色了
    queryAuthorizedRoles() {
      let rLoading = me.openLoading();
      menuRoleList({
        menuCode: me.menuInfo.code,
      })
        .then((res) => {
          rLoading.close();
          if (res.code == "200") {
            me.authorizedRoles = res.data;
          } else {
            me.$message.error(res.msg || "查询失败，请稍后再试~");
          }
        })
        .catch((err) => {
          rLoading.close();
          me.$message.error(err.statusText || "对不起，系统繁忙，请稍后再试~");
        });
    },
    // 节点是否是应用/分组。是的话，才能放置拖拽的节点。如果是菜单，不能放置
    allowDrop(draggingNode, dropNode, type) {
      if (dropNode.data.isMenu === true) {
        return type !== "inner";
      } else {
        return true;
      }
    },
    // 节点是否可以拖拽
    nodeCanDrag(node) {
      return false; // !node.data.code ? false : true;
    },
    // 拖拽节点
    handleDragNode(oldNode, newNode, e) {
      if (e == "inner") {
        me.saveDragResult(oldNode.data, newNode.data); // 调接口保存拖拽结果
      } else {
        me.saveDragResult(oldNode.data, newNode.parent.data); // 调接口保存拖拽结果
      }
    },
    //   序号获取
    indexMethod(index) {
      return index + 1;
    },
  },
};
</script>
<style lang="less" scoped>
.page-container {
  .el-form {
    /deep/.el-col {
      .el-form-item {
        .el-form-item__label {
          width: 80px;
        }

        .el-form-item__content {
          width: calc(100% - 90px);
        }
      }
    }

    .el-button--primary {
      color: #fff;
    }
  }
  .el-col-2 {
    text-align: center;
    padding-top: 30vh;
    .icon-box {
      i {
        width: 2em;
        height: 2em;
        line-height: 2em;
        border-radius: 1em;
        background-color: #ccc;
      }
      &:last-child {
        margin-top: 1em;
      }
    }
  }
  .table-buttons-box {
    display: flex;
    justify-content: space-between;
  }
}
/deep/.el-dialog {
  .el-dialog__body {
    max-height: 60vh;
    overflow: auto;
    .el-form {
      .el-form-item {
        margin-top: 1.2em;
        .el-form-item__content {
          .el-select {
            width: 100%;
          }
        }
      }
    }
  }
}
</style>
